package com.hzgj.bcl.util.reg;

import com.alibaba.fastjson.JSON;
import mousio.etcd4j.EtcdClient;
import mousio.etcd4j.promises.EtcdResponsePromise;
import mousio.etcd4j.responses.EtcdException;
import mousio.etcd4j.responses.EtcdKeysResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Created by Administrator on 2016/9/19.
 */
public class EtcdExtClient {

    protected static final Logger logger = LoggerFactory.getLogger(EtcdExtClient.class);
    private EtcdClient client;
    private int timeout = 5;
    public TimeUnit timeout_timeUnit = TimeUnit.SECONDS;

    public EtcdExtClient(int timeout, TimeUnit timeout_timeUnit, List<URI> baseUri) {
        this.client = new EtcdClient(baseUri.toArray(new URI[0]));
        this.timeout = timeout;
        this.timeout_timeUnit = timeout_timeUnit;
    }

    public <T> T getValue(String key, Class<T> type) {
        try {
            EtcdResponsePromise<EtcdKeysResponse> response = client.get(key).timeout(timeout, timeout_timeUnit).send();
            EtcdKeysResponse r = response.get();
            if (r != null) {
                return JSON.parseObject(r.node.value, type);
            }
        } catch (Exception e) {
            logger.error("{}", e);
        }
        return null;
    }

    public boolean exist(String key) {
        try {
            EtcdResponsePromise<EtcdKeysResponse> rInfo = client.get(key).timeout(timeout, timeout_timeUnit).send();
            EtcdKeysResponse r1 = rInfo.get();
            if (r1 != null) {
                return true;
            }
        } catch (EtcdException e1) {
            if (e1.errorCode != 100) {
                logger.error("{}", e1);
            }
        } catch (Exception e) {
            logger.error("{}", e);
        }
        return false;
    }

    /**
     * 數據量較小的情況下執行
     *
     * @param dir
     * @return
     * @throws Exception
     */
    public List<EtcdKeysResponse.EtcdNode> getDirWithRecursive(String dir) throws Exception {
        EtcdResponsePromise<EtcdKeysResponse> response = client.getDir(dir).recursive().timeout(timeout, timeout_timeUnit).send();
        EtcdKeysResponse r = response.get();
        if (r != null) {
            return r.node.nodes;
        }
        return null;
    }

    public EtcdResponsePromise<EtcdKeysResponse> waitForKey(String key) throws Exception {
        return client.getDir(key).waitForChange().recursive().send();
    }


    public List<EtcdKeysResponse.EtcdNode> getDir(String dir) throws Exception {
        EtcdResponsePromise<EtcdKeysResponse> response = client.getDir(dir).timeout(timeout, timeout_timeUnit).send();
        EtcdKeysResponse r = response.get();
        if (r != null) {
            return r.node.nodes;
        }
        return null;
    }

    public EtcdKeysResponse.EtcdNode getDirValue(String dir) throws Exception {
        EtcdResponsePromise<EtcdKeysResponse> response = client.getDir(dir).timeout(timeout, timeout_timeUnit).send();
        EtcdKeysResponse r = response.get();
        if (r != null) {
            return r.node;
        }
        return null;
    }

    public boolean deleteDir(String key) throws Exception {
        EtcdResponsePromise<EtcdKeysResponse> response = client.deleteDir(key).timeout(timeout, timeout_timeUnit).send();
        EtcdKeysResponse r = response.get();
        if (r != null) {
            return true;
        }
        return false;
    }

    public boolean deleteDirWithRecursive(String key) throws Exception {
        EtcdResponsePromise<EtcdKeysResponse> response = client.deleteDir(key).recursive().timeout(timeout, timeout_timeUnit).send();
        EtcdKeysResponse r = response.get();
        if (r != null) {
            return true;
        }
        return false;
    }

    public boolean put(String key, String value, int ttl) throws Exception {
        EtcdResponsePromise<EtcdKeysResponse> response = client.put(key, value).ttl(ttl).timeout(timeout, timeout_timeUnit).send();
        EtcdKeysResponse r = response.get();
        if (r != null) {
            return true;
        }
        return false;
    }

    public boolean refresh(String key, int ttl) throws Exception {
        EtcdResponsePromise<EtcdKeysResponse> response = client.refresh(key, ttl).timeout(timeout, timeout_timeUnit).send();
        EtcdKeysResponse r = response.get();
        if (r != null) {
            return true;
        }
        return false;
    }

    public void close() throws IOException {
        client.close();
    }
}
